package multithreading;

import java.util.concurrent.*;


/**
 * @Author: 海琳琦
 * @Date: 2022/4/4 17:26
 * Executor方式创建线程池对线程掌握的粒度不够，手动new ThreadPoolExecutor()创建线程池
 * 1、了解七个参数
 *          int corePoolSize：核心线程数
 *          int maximumPoolSize：最大线程数
 *          long keepAliveTime：最大空闲时间  //存活时间；当线程数超过核心线程池数量，超过存活时间会回收进入队列
 *          TimeUnit unit：时间单位
 *          BlockingQueue<Runnable> workQueue：阻塞队列
 *          ThreadFactory threadFactory：线程工厂（手动创建好处：给线程指定名称，出现问题能更好地确定位置）
 *          RejectedExecutionHandler handler：（拒绝策略）
 *
 * 2、线程的执行流程
 *          任务--->提交任务----->核心线程数有空闲------->执行任务
 *                             -->没有空闲------>放到阻塞队列---->阻塞队列没有满--->放到队列中排队
 *                                                          ----->满了---->判断工作线程数是否为最大线程数---->达到最大线程数---->拒绝策略
 *                                                                                                        --->未达到--->创建非核心线程(maximumSize - corPoolSize)
 *    面试：为什么先进阻塞再去尝试创建非核心线程（耗费资源）：
 *    饭店（线程池）- 厨子（线程）- 人多先排队（阻塞队列）- 招厨子（创建最大线程）- 今日客满（拒绝）
 *
 * 3、线程池属性
 *     //是一个int类型的数值，表达了两个意思，1：声明当前线程的状态 2：声明当前线程的线程数
 *     //高3位：线程池状态   低29位：线程池中线程的个数
 *     private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
 *     //29，方便做位运算
 *     private static final int COUNT_BITS = Integer.SIZE - 3;
 *     //最大线程容量 1<<29 -1  即低29位全为1
 *     private static final int CAPACITY   = (1 << COUNT_BITS) - 1;
 *
 *     //线程池状态
 *     // -1 二进制全为1（负数我们用的补码）  -1 << 29：高3位为111，低29位为0 代表线程池为RUNNING状态，代表正常接受任务
 *     private static final int RUNNING    = -1 << COUNT_BITS;
 *
 *     //                                               高三位：000 代表线程为shutdown状态，shutdown() 不接受新任务（内部还会处理之前在排队的任务）
 *     private static final int SHUTDOWN   =  0 << COUNT_BITS;
 *
 *     //                                               高三位：001 代表线程池为stop状态，shutdownNow() 不接受新任务（内部阻塞队列的任务不会处理，同时中断当前任务）
 *     private static final int STOP       =  1 << COUNT_BITS;
 *
 *     //                                               高三位：010 代表线程池为TIDYING，为过渡状态，代表线程即将结束
 *     private static final int TIDYING    =  2 << COUNT_BITS;
 *
 *     //                                              高三位：011 代表线程池为TERMINATED，执行terminated()代表线程结束
 *     private static final int TERMINATED =  3 << COUNT_BITS;
 *
 *
 *     //得到线程池的状态
 *     private static int runStateOf(int c)     { return c & ~CAPACITY; }
 *     //得到当前线程池的线程数量
 *     private static int workerCountOf(int c)  { return c & CAPACITY; }
 *     //为更新线程中的数值做准备
 *     private static int ctlOf(int rs, int wc) { return rs | wc; }
 *
 *  4、线程池状态的转变
 *              ->      shutdown()  ->       shutdown    -> 队列为空，工作线程为空  ->
 *    running                                                                               tidying     -> terminated() ->    terminated
 *              ->    shutdownNow() ->       stop        -> 工作线程为空  ->
 */
public class ThreadPoolCreateByHand {

    public static void main(String[] args) throws InterruptedException {

//        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
//                2,
//                4,
//                10,
//                TimeUnit.MILLISECONDS,
//                new ArrayBlockingQueue<>(2),
//                new ThreadFactory() {
//                    @Override
//                    public Thread newThread(Runnable r) {
//                        Thread t = new Thread(r);
//                        t.setName("线程1");
//                        return t;
//                    }
//                },
//                new ThreadPoolExecutor.AbortPolicy()
//        );
//
//        poolExecutor.execute(()->{
//            for (int i = 0; i < 10; i++) {
//
//            }
//        });
        ThreadPoolExecutor thread = new ThreadPoolExecutor(
                2,
                4,
                10,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(1024),
                new ThreadFactory() {
                    @Override
                    public Thread newThread(Runnable r) {
                        Thread t = new Thread();
                        t.setName("线程1");
                        return t;
                    }
                },
                new ThreadPoolExecutor.AbortPolicy()
        );

        for (int i = 0; i < 10; i++) {
            thread.execute(() -> System.out.println(1));
            Future<?> submit = thread.submit(() -> System.out.println(1));
        }
        // 优雅关闭线程池
        thread.shutdown();
        System.out.println("----");
        // 任务执行完毕后打印"Done"
        System.out.println("Done");
    }

    public static void testThread() throws InterruptedException {
        /*public ThreadPoolExecutor(
        int corePoolSize,
        int maximumPoolSize,
        long keepAliveTime,
        TimeUnit unit,
        BlockingQueue<Runnable> workQueue,
        ThreadFactory threadFactory,
        RejectedExecutionHandler handler*/



    }
}

/**
 *   5、ThreadPoolExecutor.execute的执行过程：
 *  public void execute(Runnable command) {
 *          //健壮性判断
 *         if (command == null)
 *             throw new NullPointerException();
 *
 *         //拿到了32位的int
 *         int c = ctl.get();
 *         //获得工作线程数  <  核心线程数
 *         if (workerCountOf(c) < corePoolSize) {
 *              //创建线程(核心：true)
 *             if (addWorker(command, true))
 *                  //结束
 *                 return;
 *             //如果创建线程失败（并发问题等），重新获得ctl
 *             c = ctl.get();
 *         }
 *         //判断线程是否处于Running状态，否则不接受新任务(shutdown、tidying状态)，添加到阻塞队列
 *         if (isRunning(c) && workQueue.offer(command)) {
 *              //获得ctl
 *             int recheck = ctl.get();
 *             //再次判断是否为running
 *             if (!isRunning(recheck) && remove(command))
 *                 //如果不是Running（并发问题），执行拒绝策略
 *                 reject(command);
 *             //如果线程池处于Running状态，但是工作的线程数量为0
 *             else if (workerCountOf(recheck) == 0)
 *                  //阻塞队列有任务。但没有工作线程，添加一个任务为空的工作线程来处理阻塞队列中的任务
 *                 addWorker(null, false);
 *         }
 *         // 创建非核心线程
 *         else if (!addWorker(command, false))
 *             //
 *             reject(command);
 *    }
 *
 *   6、addWorker()方法
 *   private boolean addWorker(Runnable firstTask, boolean core) {
 *         //内部for循环跳出外部for循环    break retry;
 *         retry:
 *         //外层for循环状态判断
 *         for (;;) {
 *              //获取ctl 32位
 *             int c = ctl.get();
 *             //获取线程池状态
 *             int rs = runStateOf(c);
 *
 *             //除了Running都有可能
 *             if (rs >= SHUTDOWN &&
 *                  //当处于阻塞状态，当前工作进程为null，阻塞进程不为null，则创建一个进程来处理阻塞进程
 *                 ! (rs == SHUTDOWN && firstTask == null && ! workQueue.isEmpty())
 *                 )
 *                 //re != SHUTDOWN，代表是stop或者更高的状态，不需要创建线程处理任务
 *                 //任务 != null 并且 rs不处于运行状态
 *                 //阻塞队列.isEmpty()无需处理
 *                 //构建工作线程失败（无需创建eg：stop状态）
 *                 return false;
 *
 *             //内层for循环容量判断
 *             for (;;) {
 *                  //获取线程个数
 *                 int wc = workerCountOf(c);
 *                 if (wc >= CAPACITY ||
 *                     wc >= (core ? corePoolSize : maximumPoolSize))
 *                     //当前所有线程 >= 最大容量  return false;
 *  *                  //或者 wc >= 核心线程 / 最大线程
 *                     return false;
 *                 // 将工作线程数 + 1 采用CAS的方式
 *                 if (compareAndIncrementWorkerCount(c))
 *                     // 成功就退出外侧for循环
 *                     break retry;
 *
 *                 //（失败，并发）重新获取ctl
 *                 c = ctl.get();
 *                 // 重新判断线程状态，如果没变化，继续内层循环
 *                 if (runStateOf(c) != rs)
 *                     // 状态有变化，结束这次外层循环，开始下次外层循环
 *                     continue retry;
 *             }
 *         }
 *
 *         //以上执行结果为线程数 + 1
 *         //以下真正的创建线程
 *
 *         //work开始为false
 *         boolean workerStarted = false;
 *         //work添加为false
 *         boolean workerAdded = false;
 *         //work就是工作线程
 *         Worker w = null;
 *         try {
 *             //创建work，传入任务Runnable firstTask
 *             w = new Worker(firstTask);
 *             //从work中获得线程t
 *             final Thread t = w.thread;
 *             if (t != null) {
 *                 // 获取线程池的全局锁，避免我添加任务时，其他线程干掉了线程池
 *                 final ReentrantLock mainLock = this.mainLock;
 *                 //加锁
 *                 mainLock.lock();
 *                 try {
 *                     //获得线程池的状态
 *                     int rs = runStateOf(ctl.get());
 *                     // 是Running状态，直接走
 *                     if (rs < SHUTDOWN ||
 *                         // 当线程为阻塞，并且当前阻塞队列为空-》创空任务的进程加快处理
 *                         (rs == SHUTDOWN && firstTask == null)) {
 *                         //检查t是否为运行状态
 *                         if (t.isAlive())
 *                             throw new IllegalThreadStateException();
 *                          // 把工作线程加入到集合中   HashSet<Work> works = new HashSet<Work>();
 *                         workers.add(w);
 *                         //获取工作线程的个数
 *                         int s = workers.size();
 *                         //替换最大工作线程数量
 *                         if (s > largestPoolSize)
 *                             largestPoolSize = s;
 *                         //添加工作线程标志为true
 *                         workerAdded = true;
 *                     }
 *                 } finally {
 *                     //添加成功，释放锁
 *                     mainLock.unlock();
 *                 }
 *                 if (workerAdded) {
 *                     //启动工作线程
 *                     t.start();
 *                     //启动工作线程成功
 *                     workerStarted = true;
 *                 }
 *             }
 *         } finally {
 *             //启动工作线程失败，调用一下方法
 *             if (! workerStarted)
 *                 //
 *                 addWorkerFailed(w);
 *         }
 *         //返回工作线程是否启动
 *         return workerStarted;
 *     }
 *
 *   7、Worker的封装
 *   private final class Worker
 *         extends AbstractQueuedSynchronizer
 *         implements Runnable
 *     {
 *     private static final long serialVersionUID = 6138294804551838833L;
 *
 *     final Thread thread;
 *
 *     Runnable firstTask;
 *
 *     volatile long completedTasks;
 *
 *     Worker(Runnable firstTask) {
 *         setState(-1); // inhibit interrupts until runWorker
 *         //初始化任务
 *         this.firstTask = firstTask;
 *         //类似this.thread = new Thread(worker);
 *         this.thread = getThreadFactory().newThread(this);
 *     }
 *
 *     public void run() {
 *         runWorker(this);
 *     }
 *  }
 *
 *  7.1、runWorker()方法
 *  final void runWorker(Worker w) {
 *         //获取当前线程
 *         Thread wt = Thread.currentThread();
 *         //拿到了任务
 *         Runnable task = w.firstTask;
 *         w.firstTask = null;
 *         // 先不关注(AQS中)
 *         w.unlock(); // allow interrupts
 *         //表示为true
 *         boolean completedAbruptly = true;
 *         try {
 *              //任务 != null ，执行任务    |     任务为空，通过getTask()从阻塞队列中获取任务
 *             while (task != null || (task = getTask()) != null) {
 *                 //加锁，避免你shutdown，我任务也不会中断
 *                 w.lock();
 *                 // 获取当前状态，是否大于等于stop，是则中断
 *                 if ((runStateAtLeast(ctl.get(), STOP) ||
 *                      (Thread.interrupted() &&
 *                       runStateAtLeast(ctl.get(), STOP))) &&
 *                     !wt.isInterrupted())
 *                     wt.interrupt();
 *                 try {
 *                     //执行任务前的操作
 *                     beforeExecute(wt, task);
 *                     Throwable thrown = null;
 *                     try {
 *                         //调用Runnable.run()方法，开始执行任务
 *                         task.run();
 *                     } catch (RuntimeException x) {
 *                         thrown = x; throw x;
 *                     } catch (Error x) {
 *                         thrown = x; throw x;
 *                     } catch (Throwable x) {
 *                         thrown = x; throw new Error(x);
 *                     } finally {
 *                         // 执行任务后的操作
 *                         afterExecute(task, thrown);
 *                     }
 *                 } finally {
 *                     task = null;
 *                     w.completedTasks++;
 *                     w.unlock();
 *                 }
 *             }
 *             completedAbruptly = false;
 *         } finally {
 *             processWorkerExit(w, completedAbruptly);
 *         }
 *     }
 *
 *     7.2  getTask()、processWorkerExit(w, completedAbruptly);
 */






